import classNames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';

import moment, { Moment } from 'moment';
import 'moment/locale/zh-cn';

import { IControledDOMProps } from '../../utils/props';

import { Collapse } from '../collapse';
import { Icon } from '../icon';
import { Text } from '../text';
import { createDateRangeItem, getRange, IDateRange, IDateRangePanelItem, IDateRangeValue } from './dateRangeUtil';

export type Moment = Moment;

export interface IDateRangeInitialValue {
  year: number;
  value: number;
}

export interface IDateRangePickerProps extends IControledDOMProps {
  className?: string;
  style?: React.CSSProperties;
  placeholder?: string;
  open?: boolean;
  type?: string;
  value?: IDateRangeInitialValue;
  onChange?: (value: IDateRange) => void;
  disabledYear?: (year: number) => boolean;
  startYear?: number;
  endYear?: number;
}

export interface IDateRangePickerState {
  type: string;
  initialOpen?: boolean;
  open: boolean;
  year: number;
  selectedItemIndex: number;
  selectedYear: number;
  showValue?: string;
  disabledPrevBtn: boolean;
  disabledNextBtn: boolean;
}

export type GetRange = (value: IDateRangeValue) => IDateRange;

export interface IDateRangePickerControllerProps {
  onClick: (e: React.MouseEvent) => void;
  placeholder?: string;
  value?: string;
  [key: string]: any;
}
const DateRangePickerController: React.SFC<IDateRangePickerControllerProps> =
  (props: IDateRangePickerControllerProps) => {
    return (
      <div className="date-range-picker__controller" onClick={props.onClick}>
        <input
          className="date-range-picker__controller__input"
          placeholder={props.placeholder}
          readOnly
          tabIndex={-1}
          value={props.value}
        />
        <Icon className="date-range-picker__header__icon" size={14} type="date" color="#277cbd" />
      </div>
    );
  };

export interface IDateRangeHeaderProps {
  type?: string;
  year: number;
  disabledPrevBtn: boolean;
  disabledNextBtn: boolean;
  onPrevClick?: (e: React.MouseEvent) => void;
  onNextClick?: (e: React.MouseEvent) => void;
  onItemClick?: (item: IDateRangePanelItem) => void;
}

const DateRangeHeader: React.SFC<IDateRangeHeaderProps> = (props: IDateRangeHeaderProps) => {
  return (
    <div className="date-range-picker__header">
      <div>
        <Icon
          className={classNames('date-range-picker__header__prev-year-btn pull-left ', {
            'icon--disabled': props.disabledPrevBtn,
          })}
          type="left"
          size={14}
          onClick={props.onPrevClick} />
        <Text
          className={`date-range-picker__header__${props.type}-title`}
          color="#262626"
          bold>{props.year + ' 年'}</Text>
        <Icon
          className={classNames('date-range-picker__header__next-year-btn pull-right ', {
            'icon--disabled': props.disabledNextBtn,
          })}
          type="right"
          size={14}
          onClick={props.onNextClick} />
        {props.type === 'week' ?
          <span className="date-range-picker__header__year-btn pull-right"
            onClick={() => props.onItemClick && props.onItemClick({
              name: '全年',
              value: -1,
              year: props.year,
            })}
          >全年</span> : null}
      </div>
    </div>
  );
};

export interface IDateRangePanelProps {
  year: number;
  startYear?: number;
  endYear?: number;
  type?: string;
  selectedYear: number;
  selectedItemIndex: number;
  onItemClick: (item: IDateRangePanelItem) => void;
}

const DateRangePanel: React.SFC<IDateRangePanelProps> = (props: IDateRangePanelProps) => {
  let items: IDateRangePanelItem[] = createDateRangeItem(
    props.type || 'month', props.year,
    props.startYear, props.endYear,
  );

  return (
    <div className="date-range-picker__panel">
      <ul className={`date-range-picker__${props.type}-panel`}>
        {
          items.map((item: IDateRangePanelItem, index: number) => {
            return props.type !== 'week' ?
              <li key={index}
                className={item.value === props.selectedItemIndex && props.year === props.selectedYear ?
                  'date-range-picker__panel-item date-range-picker__panel-item--active' :
                  'date-range-picker__panel-item'}
                onClick={() => { props.onItemClick(item); }}>{item.name}</li> :
              <li key={index}
                className={item.value === props.selectedItemIndex && props.year === props.selectedYear ?
                  'date-range-picker__panel-item date-range-picker__panel-item--active' :
                  'date-range-picker__panel-item'}
                onClick={() => { props.onItemClick(item); }}>
                <div>
                  <span>{index + 1}</span>
                  <span>
                    {moment().year(item.year || props.year).isoWeek(item.value).startOf('isoWeek').format('M月D日')}
                  </span>
                </div>
              </li>;
          })
        }
      </ul>
    </div>
  );
};

export function getShowValue(value?: IDateRangeInitialValue, type?: string): string {
  let showValue: string = '';

  if (value) {
    if (value.value === -1 && type !== 'year') {
      showValue = `${value.year}年 全年`;
      return showValue;
    }
    switch (type) {
      case 'week':
        showValue = `${value.year}` + `第${value.value}周`;
        break;
      case 'month':
        showValue = `${value.year}` + ` ${value.value}月`;
        break;
      case 'quarter':
        showValue = `${value.year}` + ` 第${value.value}季度`;
        break;
      case 'half':
        showValue = `${value.year}` + ` ${value.value === 1 ? '上半年' : '下半年'}`;
        break;
      case 'year':
        showValue = `${value.year} 年`;
        break;
    }
  }

  return showValue;
}

export class DateRangePicker extends React.Component<IDateRangePickerProps, IDateRangePickerState> {
  public static getRange: GetRange = getRange;

  public static propTypes = {
    type: PropTypes.oneOf(['week', 'month', 'quarter', 'half', 'year']),
  };

  public static defaultProps = {
    type: 'month',
  };

  public static getDerivedStateFromProps(nextProps: IDateRangePickerProps, prevState: IDateRangePickerState) {
    if (nextProps.type !== prevState.type || nextProps.open !== prevState.initialOpen) {
      return {
        type: nextProps.type,
        year: nextProps.value && nextProps.value.year || moment().year(),
        selectedItemIndex: nextProps.value && nextProps.value.value || 0,
        open: nextProps.open || false,
        initialOpen: nextProps.open,
        showValue: '',
        disabledPrevBtn: false,
        disabledNextBtn: false,
      };
    }
    return null;
  }

  constructor(props: IDateRangePickerProps) {
    super(props);

    let showValue: string = getShowValue(props.value, props.type);

    this.state = {
      initialOpen: props.open,
      open: props.open || false,
      type: props.type || 'month',
      year: props.value && props.value.year || moment().year(),
      selectedItemIndex: props.value && props.value.value || 0,
      selectedYear: props.value && props.value.year || moment().year(),
      showValue,
      disabledPrevBtn: false,
      disabledNextBtn: false,
    };

    this.closeDateRangePicker = this.closeDateRangePicker.bind(this);
    this.onOpenClick = this.onOpenClick.bind(this);
    this.onPrevClick = this.onPrevClick.bind(this);
    this.onNextClick = this.onNextClick.bind(this);
    this.onItemClick = this.onItemClick.bind(this);
  }

  public componentDidMount() {
    document.addEventListener('click', this.closeDateRangePicker);
  }

  public componentWillUnmount() {
    document.removeEventListener('click', this.closeDateRangePicker);
  }

  public componentDidUpdate() {
    document.addEventListener('click', this.closeDateRangePicker);
  }

  public closeDateRangePicker() {
    this.setState({ open: false });
  }

  public onOpenClick(e: React.MouseEvent) {
    e.nativeEvent.stopImmediatePropagation();
    const open = !this.state.open;
    this.setState({ open });
  }

  public onPrevClick(e: React.MouseEvent) {
    e.nativeEvent.stopImmediatePropagation();
    const { disabledYear, startYear, endYear } = this.props;
    let year = this.state.year;
    year--;
    if (disabledYear && !disabledYear(year) || startYear && endYear
      && (startYear < endYear ? year < startYear : year < endYear)) {
      this.setState({
        disabledPrevBtn: true,
      });
      return;
    }
    this.setState({
      year,
      disabledPrevBtn: false,
      disabledNextBtn: false,
    });
  }

  public onNextClick(e: React.MouseEvent) {
    e.nativeEvent.stopImmediatePropagation();
    const { disabledYear, startYear, endYear } = this.props;
    let year = this.state.year;
    year++;
    if (disabledYear && !disabledYear(year) || startYear && endYear
      && (startYear < endYear ? year > endYear : year > startYear)) {
      this.setState({
        disabledNextBtn: true,
      });
      return;
    }
    this.setState({
      year,
      disabledPrevBtn: false,
      disabledNextBtn: false,
    });
  }

  public onItemClick(item: IDateRangePanelItem) {
    const { onChange, type } = this.props;
    let showValue = '';
    showValue += type === 'year' ? item.name : this.state.year + ' ' + item.name;
    this.setState({
      selectedItemIndex: item.value,
      selectedYear: this.state.year,
      showValue,
      open: false,
    }, () => {
      let year = this.state.selectedYear;
      let dateType = this.state.type;
      let dateRange = getRange({
        year,
        type: dateType,
        ...item,
      }, true);
      if (onChange) {
        onChange(dateRange);
      }
    });
  }

  public render() {
    const { className, style, type, placeholder, startYear, endYear, ...domProps } = this.props;
    const { year, open, selectedItemIndex, showValue, selectedYear, disabledPrevBtn, disabledNextBtn } = this.state;
    return (
      <div
        {...domProps as IControledDOMProps}
        className={classNames('date-range-picker', className)}
        style={style}
      >
        <DateRangePickerController onClick={this.onOpenClick} placeholder={placeholder} value={showValue} />
        <div className={'date-range-picker__container ' + `date-range-picker__${type}-container `}>
          <div className="date-range-picker__panel-container"
            onClick={(e: React.MouseEvent) => { e.nativeEvent.stopImmediatePropagation(); }}>
            <Collapse active={open} config="stiff">
              {
                type !== 'year' ?
                  <DateRangeHeader
                    type={type}
                    year={year}
                    disabledPrevBtn={disabledPrevBtn}
                    disabledNextBtn={disabledNextBtn}
                    onPrevClick={this.onPrevClick}
                    onNextClick={this.onNextClick}
                    onItemClick={this.onItemClick} /> : null
              }
              <DateRangePanel
                type={type}
                year={year}
                startYear={startYear}
                endYear={endYear}
                selectedYear={selectedYear}
                selectedItemIndex={selectedItemIndex}
                onItemClick={this.onItemClick} />
            </Collapse>
          </div>
        </div>
      </div>
    );
  }
}
